package com.enation.app.javashop.buyer.api.trade;

import com.enation.app.javashop.core.promotion.shetuan.service.ShetuanCartManager;
import com.enation.app.javashop.core.shop.model.dos.ShopDetailDO;
import com.enation.app.javashop.core.shop.model.vo.ShopVO;
import com.enation.app.javashop.core.shop.service.ShopManager;
import com.enation.app.javashop.core.trade.TradeErrorCode;
import com.enation.app.javashop.core.trade.cart.model.enums.CartSourceType;
import com.enation.app.javashop.core.trade.cart.model.enums.CheckedWay;
import com.enation.app.javashop.core.trade.cart.model.vo.*;
import com.enation.app.javashop.core.trade.cart.service.CartOriginDataManager;
import com.enation.app.javashop.core.trade.cart.service.CartReadManager;
import com.enation.app.javashop.core.trade.order.model.vo.CheckoutParamVO;
import com.enation.app.javashop.core.trade.order.service.CheckoutParamManager;
import com.enation.app.javashop.framework.context.UserContext;
import com.enation.app.javashop.framework.exception.ServiceException;
import com.enation.app.javashop.framework.security.model.Buyer;
import com.enation.app.javashop.framework.util.IpUtil;
import com.google.common.collect.Maps;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import org.apache.commons.lang.ArrayUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.MediaType;
import org.springframework.util.CollectionUtils;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import springfox.documentation.annotations.ApiIgnore;

import javax.servlet.http.HttpServletRequest;
import javax.validation.constraints.Max;
import javax.validation.constraints.Min;
import javax.validation.constraints.NotNull;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * 购物车接口
 *
 * @author Snow
 * @version v1.0
 * 2018年03月19日21:40:52
 * @since v7.0.0
 */
@Api(description = "购物车接口模块")
@RestController
@RequestMapping("/trade/carts")
@Validated
public class    CartBuyerController {

    @Autowired
    private CartReadManager cartReadManager;

    @Autowired
    private CartOriginDataManager cartOriginDataManager;

    @Autowired
    private ShetuanCartManager shetuanCartManager;

    @Autowired
    private CheckoutParamManager checkoutParamManager;

    @Autowired
    private ShopManager shopManager;

    private final Log logger = LogFactory.getLog(getClass());


    /**
     * -查询用户所有缓存购物车商品->按照店铺groupby 购物车->校验失效（已打样非快递 || 商品信息变更）->渲染促销信息
     * 购物车详情  渲染sku->校验sku是否有效->渲染促销规则->计算价格->生成成品
     *
     * @param cartSourceType 购物车类型
     * @return
     */
    @ApiOperation(value = "获取购物车页面购物车详情")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "cart_source_type", value = "SHETUAN_CART：社区团购购物车，COMMON_CART：普通购物车", allowableValues = "SHETUAN_CART,COMMON_CART", paramType = "path",required = true, dataType = "String"),
            @ApiImplicitParam(name = "way", value = "BUY_NOW：立即购买，CART：购物车购买", allowableValues = "BUY_NOW,CART", paramType = "query",required = true, dataType = "String"),
            @ApiImplicitParam(name = "city", value = "当前定位城市", paramType = "query",required = true, dataType = "String"),
    })
    @GetMapping("/all/{cart_source_type}")
    public CartView cartAll(@PathVariable("cart_source_type") String cartSourceType,@RequestParam(value = "way",required = false)  String way,@RequestParam(value = "city",required = false)  String city, HttpServletRequest request) {
        way=StringUtils.isEmpty(way)?CheckedWay.CART.name():way;
        try {
            CartView cartView = null;
            // 查询普通商品购物车 && 社区团购购物车
            if(cartSourceType.equals(CartSourceType.SHETUAN_CART.name())){
                logger.info("用户所在城市："+city);
                // 设置定位城市
                checkoutParamManager.setCity(city);
                // 购物车查询
                cartView= this.shetuanCartManager.getCartListAndCountPrice(CheckedWay.valueOf(way));
                // 统计购物车商品数量
                cartView.statisticSkuNum();
            }else {
                cartView = this.cartReadManager.getCartListAndCountPrice(CheckedWay.valueOf(way));
            }
            return cartView;
        } catch (Exception e) {
            logger.error("读取购物车异常", e);
            return new CartView(new ArrayList<>(), new PriceDetailVO());
        }
    }

    /**
     * 本地线程保存登录用户信息，随时获取用户对应购物车缓存  SelectedPromotionVo
     * 读取缓存待添加sku信息—>校验—>读取购物车已存在sku—>校验（不存在 已存在）—> 填充商品促销信息（单品优惠&&组合优惠-满减）->压入Redis缓存
     *
     * @param skuId
     * @param num
     * @param activityId
     * @return
     */
    @ApiOperation(value = "向购物车中添加一个产品", response = CartSkuVO.class)
    @ApiImplicitParams({
            @ApiImplicitParam(name = "sku_id", value = "产品ID", required = true, dataType = "int", paramType = "query"),
            @ApiImplicitParam(name = "num", value = "此产品的购买数量", required = true, dataType = "int", paramType = "query"),
            @ApiImplicitParam(name = "activity_id", value = "默认参与的活动id（没有随机第一个活动）", dataType = "int", paramType = "query")
    })
    @ResponseBody
    @PostMapping(produces = MediaType.APPLICATION_JSON_VALUE)
    public CartSkuOriginVo add(@ApiIgnore @NotNull(message = "产品id不能为空") Integer skuId,
                               @ApiIgnore @NotNull(message = "购买数量不能为空") @Min(value = 1, message = "加入购物车数量必须大于0") Integer num,
                               @ApiIgnore Integer activityId) {
        return cartOriginDataManager.add(skuId, num, activityId);
    }

    /**
     * @param skuId
     * @param num
     * @param activityId
     */
    @ApiOperation(value = "立即购买", response = CartSkuVO.class)
    @ApiImplicitParams({
            @ApiImplicitParam(name = "sku_id", value = "产品ID", required = true, dataType = "int", paramType = "query"),
            @ApiImplicitParam(name = "num", value = "此产品的购买数量", required = true, dataType = "int", paramType = "query"),
            @ApiImplicitParam(name = "activity_id", value = "默认参与的活动id", dataType = "int", paramType = "query"),
    })
    @ResponseBody
    @PostMapping("/buy")
    public CartSkuOriginVo buy(@ApiIgnore @NotNull(message = "产品id不能为空") Integer skuId,
                    @ApiIgnore @NotNull(message = "购买数量不能为空") @Min(value = 1, message = "购买数量必须大于0") Integer num,
                    @ApiIgnore Integer activityId) {
        Integer memberId=UserContext.getBuyer().getUid();
        return  cartOriginDataManager.buy(skuId, num, activityId,memberId);
    }

    /**
     * 更新【购物车商品数量】和【商品是否选中结算】
     * @param skuId
     * @param checked
     * @param num
     */
    @ApiOperation(value = "更新购物车中的多个产品", notes = "更新购物车中的多个产品的数量或选中状态")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "sku_id", value = "产品id数组", required = true, dataType = "int", paramType = "path"),
            @ApiImplicitParam(name = "checked", value = "是否选中", dataType = "int", paramType = "query", allowableValues = "0,1"),
            @ApiImplicitParam(name = "num", value = "产品数量", dataType = "int", paramType = "query"),
            @ApiImplicitParam(name = "cart_source_type", value = "SHETUAN_CART：社区团购购物车，COMMON_CART：普通购物车", allowableValues = "SHETUAN_CART,COMMON_CART", paramType = "query",required = true, dataType = "String")
    })
    @ResponseBody
    @PostMapping(value = "/sku/{sku_id}", produces = MediaType.APPLICATION_JSON_VALUE)
    public void update(@ApiIgnore @NotNull(message = "产品id不能为空") @PathVariable(name = "sku_id") Integer skuId,
                       @Min(value = 0) @Max(value = 1) Integer checked,
                       Integer num,
                       String cartSourceType) {
        // 先更新社区团购物车 在更新普通商品购物车
        if (checked != null) {
            cartOriginDataManager.checked(skuId, checked,cartSourceType);
        } else if (num != null) {
            cartOriginDataManager.updateNum(skuId, num,cartSourceType);
        }
    }


    @ApiOperation(value = "批量设置某商家的商品为选中或不选中")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "seller_id", value = "卖家id", required = true, dataType = "int", paramType = "path"),
            @ApiImplicitParam(name = "cart_source_type", value = "SHETUAN_CART：社区团购购物车，COMMON_CART：普通购物车", allowableValues = "SHETUAN_CART,COMMON_CART", required = true, dataType = "String",paramType = "query"),
            @ApiImplicitParam(name = "checked", value = "是否选中", required = true, dataType = "int", paramType = "query", allowableValues = "0,1")
    })
    @ResponseBody
    @PostMapping(value = "/seller/{seller_id}", produces = MediaType.APPLICATION_JSON_VALUE)
    public void updateSellerAll(@NotNull(message = "卖家id不能为空") @PathVariable(name = "seller_id") Integer sellerId,
                                @NotNull(message = "必须指定是否选中") @Min(value = 0) @Max(value = 1) Integer checked,
                                String cartSourceType) {
        if (checked != null && sellerId != null) {
            cartOriginDataManager.checkedSeller(sellerId, checked,cartSourceType);
        }
    }

    @ApiOperation(value = "删除购物车中的一个或多个产品")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "sku_ids", value = "产品id，多个产品可以用英文逗号：(,) 隔开", required = true, dataType = "int", paramType = "path", allowMultiple = true),
            @ApiImplicitParam(name = "cart_source_type", value = "SHETUAN_CART：社区团购购物车，COMMON_CART：普通购物车", allowableValues = "SHETUAN_CART,COMMON_CART", required = true, dataType = "String")
    })
    @DeleteMapping(value = "/{sku_ids}/sku")
    public void delete(@PathVariable(name = "sku_ids") Integer[] skuIds,String cartSourceType) {

        if (skuIds.length == 0) {
            throw new ServiceException(TradeErrorCode.E455.code(), "参数异常");
        }
        cartOriginDataManager.delete(skuIds,cartSourceType);

    }

    @ApiOperation(value = "统计购物车商品数量")
    @GetMapping("/cartCount")
    public Map<String, Integer> cartCount(@RequestParam(value = "city") String city) {
        List<CartSkuOriginVo> commonCartList = cartOriginDataManager.read(CheckedWay.CART, CartSourceType.COMMON_CART);
        List<CartSkuOriginVo> shetuanCartList = cartOriginDataManager.read(CheckedWay.CART, CartSourceType.SHETUAN_CART);

        //1、定义需要返回的数据
        //商城购物车商品数量
        Integer commonCartGoodsNum = commonCartList.size();
        //社团购物车商品数量
        Integer shetuanCartGoodsNum = 0;
        //社团购物车中的sku数量
        Integer shetuanCartSkuNum = 0;

        //2、获取所在城市
        Integer sellerId = shopManager.getShopByCity(city);

        //3、获取购物车中商品的店铺信息
        if(sellerId>0){
            shetuanCartList = shetuanCartList.stream().filter(cartSkuOriginVo -> (cartSkuOriginVo.getSellerId().equals(sellerId)) && cartSkuOriginVo.getChecked()==1).collect(Collectors.toList());
            if(!CollectionUtils.isEmpty(shetuanCartList)){
                for (CartSkuOriginVo cartSkuOriginVo : shetuanCartList) {
                    shetuanCartGoodsNum += 1;
                    shetuanCartSkuNum += cartSkuOriginVo.getNum();
                }
            }
        }

        Map<String, Integer> countResult = Maps.newHashMap();
        countResult.put("COMMON_CART", commonCartGoodsNum);
        countResult.put("SHETUAN_CART", shetuanCartGoodsNum);
        countResult.put("SHETUAN_CART_SKU_NUM", shetuanCartSkuNum);
        countResult.put("TOTAL_CART", shetuanCartGoodsNum + commonCartGoodsNum);
        return countResult;
    }

    //===============================================================================================================================
    //=============================================              结算页面            =================================================
    //===============================================================================================================================


    /**
     * 2020-06 购物车按照店铺分别进行结算
     * 立即购买 购物车购买
     * @param sellerId 店铺id
     * @param way      购买方式  FIX
     * @param cartSourceType 购物车类型
     * @return
     */
    @ApiOperation(value = "获取结算页面购物车详情【单个店铺】")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "way", value = "结算页面方式，BUY_NOW：立即购买，CART：购物车", required = true, dataType = "String"),
            @ApiImplicitParam(name = "cartSourceType", allowableValues = "SHETUAN_CART,COMMON_CART", paramType = "query",required = true, dataType = "String")
    })
    @GetMapping("/checkedSingle")
    public CartView cartCheckedSingle(@RequestParam(value = "sellerId", required = false) Integer sellerId, @RequestParam(value = "way") String way, @RequestParam(value = "cartSourceType") String cartSourceType) {
        CartView cartView = null;
        // 查询结算详情信息
        CartSourceType cartSourceTypeEnum = CartSourceType.valueOf(cartSourceType);
        switch (cartSourceTypeEnum) {
            case SHETUAN_CART:
                // 社区团购购物车结算详情（根据提货时间拆分多个cart）
                cartView = this.shetuanCartManager.getCheckedItems(CheckedWay.valueOf(way), sellerId);
                break;
            case COMMON_CART:
                // 普通商品购物车结算详情
                cartView = this.cartReadManager.getCheckedItems(CheckedWay.valueOf(way), sellerId);
                break;
            default:
                throw new ServiceException("500", "未知购物车结算类型-普通订单-社区团购订单!");
        }
        return cartView;
    }

    @ApiOperation(value = "获取单店铺的购物车详情")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "way", value = "结算页面方式，BUY_NOW：立即购买，CART：购物车", required = true, dataType = "String"),
     })
    @GetMapping("/getSellerCart")
    public CartView getSellerCart(@RequestParam(value = "sellerId", required = false) Integer sellerId, @RequestParam(value = "way") String way) {
        CartView cartView = this.cartReadManager.getSellerCart(CheckedWay.valueOf(way), sellerId);

        return this.cartReadManager.getSellerCart(CheckedWay.valueOf(way), sellerId);
    }

}
